#include <stdio.h>
#include "ofc/DFSM.h"

enum
{
  INSERT_CARD,
  ENTER_PIN,
  REFUSE_PIN,
  ENTER_AMOUNT,
  ACCEPT_MONEY,
  REMOVE_CARD
};

int main(int argc, char *argv[])
{
  DFSM *fsm = [DFSM new];

  DFSMState *waitCard    = [DFSMState new]; // State: wait for card
  DFSMState *waitPin     = [DFSMState new]; // State: wait for pin
  DFSMState *waitAmount  = [DFSMState new]; // State: wait for choice amount money
  DFSMState *waitAccept  = [DFSMState new]; // State: wait for acceptance money
  DFSMState *waitRemoval = [DFSMState new]; // State: wait for removal card

  DBitArray *events      = [DBitArray alloc]; // the events bit array

  [events init :INSERT_CARD :REMOVE_CARD]; // Init the events bit array 

                                       // Setup the state machine
  [events reset]; [events set :INSERT_CARD];
  [fsm transition :waitCard :[events copy] :waitPin];
  
  [events reset]; [events set :ENTER_PIN];
  [fsm transition :waitPin :[events copy] :waitAmount];

  [events reset]; [events set :REFUSE_PIN];
  [fsm transition :waitPin :[events copy] :waitRemoval];

  [events reset]; [events set :ENTER_AMOUNT];
  [fsm transition :waitAmount :[events copy] :waitAccept];

  [events reset]; [events set :ACCEPT_MONEY];
  [fsm transition :waitAccept :[events copy] :waitRemoval];

  [events reset]; [events set :REMOVE_CARD];
  [fsm transition :waitRemoval :[events copy] :waitCard];

                                       // Start using the state machine
  [fsm start :waitCard];
                                       // Feed the state machine with events
  if ([fsm feed :INSERT_CARD] != nil)
    printf("Event INSERT_CARD accepted.\n");
  else 
    printf("Event INSERT_CARD was not allowed in the current state.\n");

                                       // Try an event in the current state
  printf("Event: ENTER_PIN is %s accaptable in the current state.\n", ([fsm try :ENTER_PIN] != nil ? "" : "not"));

  if ([fsm feed :REFUSE_PIN] == waitRemoval)
    printf("Event REFUSE_PIN accepted and fsm is moved to waitRemoval.\n");
  else
    printf("Event REFUSE_PIN not accepted.\n");

  [fsm free];                          // Cleanup fsm, states and transations
  [events free];

  return 0;
}

